package org.dreamwork.tools.network.bridge.client.fx;

import javafx.fxml.FXMLLoader;
import javafx.fxml.JavaFXBuilderFactory;
import javafx.geometry.Dimension2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.dreamwork.config.KeyValuePair;
import org.dreamwork.tools.network.bridge.client.fx.controllers.AbstractController;
import org.dreamwork.tools.network.bridge.client.fx.controllers.AbstractWebPage;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class StageManager {
    public static final class Holder<T> {
        public T controller;
        public Parent root;
        public Stage stage;
    }

    public static <T> Holder<T> load (URL url, ResourceBundle bundle) throws IOException {
        return load (createLoader (url), bundle);
    }

    public static <T> Holder<T> load (String url, ResourceBundle bundle) throws IOException {
        return load (createLoader (url), bundle);
    }

    public static <T> Holder<T> load (FXMLLoader loader, ResourceBundle bundle) throws IOException {
        Holder<T> holder  = new Holder<> ();
        if (bundle != null) {
            loader.setResources (bundle);
        }
        holder.root       = loader.load ();
        holder.controller = loader.getController ();

        return holder;
    }

    public static <T extends AbstractController> Holder<T> showStage (String fxml, ResourceBundle bundle, Modality modality) throws IOException {
        Holder<T> holder = load (createLoader (fxml), bundle);
        Scene scene = new Scene (holder.root);
        Stage stage = new Stage ();
        stage.setScene (scene);
        if (modality != null) {
            stage.initModality (modality);
        }
        stage.show ();
        holder.stage = stage;
        return holder;
    }

    public static <T extends AbstractController> Holder<T> showStage (String fxml, ResourceBundle bundle, String title, boolean resizable) {
        try {
            Holder<T> h = showStage (fxml, bundle, Modality.APPLICATION_MODAL);
            h.controller.setStage (h.stage, title);
            h.stage.setResizable (resizable);
            return h;
        } catch (Exception ex) {
            ex.printStackTrace ();
            DialogHelp.error (ex.getMessage (), ex);
        }
        return null;
    }

    private static FXMLLoader createLoader (String url) {
        ClassLoader loader = StageManager.class.getClassLoader ();
        return createLoader (loader.getResource (url));
    }

    private static FXMLLoader createLoader (URL url) {
        FXMLLoader loader = new FXMLLoader (url);
        loader.setBuilderFactory (new JavaFXBuilderFactory ());
//        loader.setResources (Context.ui);
        return loader;
    }

    private static final URL WEB_VIEW   = StageManager.class.getClassLoader ().getResource ("jfx/main-2.fxml");
    private static final URL MODAL_VIEW = StageManager.class.getClassLoader ().getResource ("jfx/modal.fxml");

    static void loadPage (AbstractWebPage page, Stage stage, double width, double height, boolean resizable, boolean modal, String title, KeyValuePair<?>... parameters) throws IOException {
        URL url = resizable ? WEB_VIEW : MODAL_VIEW;
        FXMLLoader fxml = new FXMLLoader (url, GuiContext.ui, new JavaFXBuilderFactory ());
        fxml.setController (page);
        Parent root = fxml.load ();
        Scene scene = new Scene (root, width, height);

        AbstractWebPage web = fxml.getController ();
        if (stage == null) {
            stage = new Stage ();
        }
        web.setStage (stage);
        web.setTitle (title, parameters);
        stage.setScene (scene);
        if (modal) {
            stage.initModality (Modality.APPLICATION_MODAL);
        }
        stage.setResizable (resizable);
        stage.initStyle (StageStyle.TRANSPARENT);
        stage.show ();
    }

    public static void loadPage (AbstractWebPage page, Stage stage, String title, KeyValuePair<?>... parameters) throws IOException {
        if (page != null) {
            Dimension2D size = page.getSize ();
            double width = 600, height = 400;
            if (size != null) {
                width  = size.getWidth ();
                height = size.getHeight ();
            }
            loadPage (page, stage, width, height, false, true, title, parameters);
        } else {
            throw new NullPointerException ("page is null");
        }
    }

    public static void loadPage (AbstractWebPage page, String title, KeyValuePair<?>... parameters) throws IOException {
        if (page != null) {
            Dimension2D size = page.getSize ();
            double width = 600, height = 400;
            if (size != null) {
                width  = size.getWidth ();
                height = size.getHeight ();
            }
            loadPage (page, width, height, title, parameters);
        } else {
            throw new NullPointerException ("page is null");
        }
    }

    public static void loadPage (AbstractWebPage page, double width, double height, String title, KeyValuePair<?>... parameters) throws IOException {
        loadPage (page, new Stage (), width, height, false, true, title, parameters);
    }
}
